`timescale 1ns/1ns
module stage1 (
	valid_0_1,
	data_0_1,
	valid_1_2,
	data_1_2,
	msg_end_1_2,
	
	clk,
	rst	//P RST
);
		
	parameter [2:0]
		
		IDLE	=	3'b000,
		SOH	=	3'b001,	//in state SOH = SOH made a match
		VER	=	3'b010,
		PKT	=	3'b011,
		MSGN  =  3'b100,
		LEN	=	3'b101,
		DCD	=	3'b110
		
		;

	input 			clk;
	input 			rst;
	input 			valid_0_1;
	input 	[7:0] data_0_1;
	output			valid_1_2;
	output	[7:0]	data_1_2;
	output			msg_end_1_2;

	wire				valid_0_1;
	wire 		[7:0]	data_0_1;
	reg		[2:0] cst;
	reg		[2:0] nst;
	reg		[2:0] lst;
	reg				valid_1_2;
	reg		[7:0]	data_1_2;
	reg				msg_end_1_2;

	reg		[3:0] pkt_counter;
	reg		[1:0] msgn_counter;
	reg		[7:0] byte_counter;
	reg		[7:0] byte_len;
	reg		[7:0] msg_num;
	reg		[7:0] msg_total;

	always @(posedge clk or posedge rst)
	begin
		if(rst)
		begin
			cst	<=	IDLE;
			lst	<=	IDLE;
		end
		else
		begin
			cst	<=	nst;
			lst	<=	cst;
		end
	end

	always @(posedge clk or posedge rst)
	begin
		if(rst)
			msg_total	<=	0;
		else
			if(cst==MSGN)
					msg_total	<=	( data_0_1 - 48 ) + msg_total * 10 ;
			else
					msg_total	<=	msg_total;
	end
	
	always @(cst or valid_0_1 or data_0_1 or pkt_counter or msgn_counter or msg_num or byte_counter or byte_len)
	begin
		case(cst)
			IDLE:
				nst	=	SOH;
			SOH:
				begin
					if(valid_0_1)
						nst	=	(data_0_1==8'h01)	?	VER : IDLE	;
					else
						nst	=	nst;
				end
			VER:
				begin
					if(valid_0_1)
						
						nst	=	(data_0_1==8'h02)	?	PKT : IDLE	;
					else
						nst	=	nst;
				end
			PKT: 
				begin
					if(pkt_counter==4'b1001)
						nst	=	MSGN;
					else
						nst	=	PKT;
				end
			MSGN:
				begin
					if(msgn_counter==2'b10)
						nst	=	LEN;
					else
						nst	=	MSGN;
				end
			LEN:
				begin
					if(msg_num==msg_total)	//value determined by previous field
						nst	=	IDLE;
					else
						nst	=	DCD;
				end
			DCD: 
				begin
					if(byte_counter == byte_len-1)
						if(byte_len==8'hff)
							if(data_0_1==8'h03)
								nst	=	LEN;
							else
								nst	=	DCD;
						else
							nst	=	LEN;
				end
		endcase
	end	
	
	always @(posedge rst or posedge clk)
	begin
		if(rst)
			begin
				pkt_counter	<=	4'b0;
				msgn_counter <= 2'b0;
				byte_counter <= 8'b0;
				msg_num		<=	8'b0;
				byte_len		<=	8'b0;
				valid_1_2	<=	0;
				data_1_2		<=	0;
				msg_end_1_2	<=	0;
				//msg_total	<=	0;
			end
		else
			begin
				case(cst)
					IDLE:
						begin
							valid_1_2	<=	0;
							data_1_2		<=	0;
							msg_end_1_2	<=	0;
						end
					SOH:
						begin
							valid_1_2	<=	0;
							data_1_2		<=	0;
							msg_end_1_2	<=	0;
						end
					VER:
						begin
							valid_1_2	<=	0;
							data_1_2		<=	0;
							msg_end_1_2	<=	0;
						end
					PKT:
						begin
							valid_1_2	<=	0;
							data_1_2		<=	0;
							msg_end_1_2	<=	0;
							if(pkt_counter==4'b1001)
								pkt_counter <= 0;
							else
								pkt_counter <= pkt_counter + 1;
						end
					MSGN:
						begin
							valid_1_2	<=	0;
							data_1_2		<=	0;
							msg_end_1_2	<=	0;
							msg_num		<=	0;
							if(msgn_counter==2'b10)
								msgn_counter	<=	0;
							else
								begin
									//msg_total	<=	( data_0_1 - 48 ) + msg_total * 10 ;
									msgn_counter	<=	msgn_counter + 1;
								end
						end
					LEN:
						begin
							valid_1_2	<=	0;
							data_1_2		<=	0;
							msg_end_1_2	<=	0;
							byte_len		<=	data_0_1;
							byte_counter	<=	0;
						end
					DCD:
						begin
							msg_num		<=	msg_num + 1;		
							if(byte_counter == byte_len-1)		
								if(byte_len == 8'hff)	//long msg, delimited by ETX
									begin
										if(data_0_1==8'h03)
											begin
												valid_1_2	<=	0;
												data_1_2		<=	0;
												msg_end_1_2		<=	1;
												byte_counter 	<=	0;
											end
										else
											begin
												valid_1_2	<=	1;
												data_1_2		<=	data_0_1;
												msg_end_1_2		<=	0;
												byte_counter	<=	byte_counter + 1;
											end
									end
								else	//not long msg, delimit by byte_len
								begin
									valid_1_2	<=	1;
									data_1_2		<=	data_0_1;
									msg_end_1_2		<=	1;
									byte_counter 	<=	0;
								end
							else
								begin
									valid_1_2	<=	1;
									data_1_2		<=	data_0_1;
									msg_end_1_2		<=	0;
									byte_counter	<=	byte_counter + 1;
								end
						end
			endcase
		end
	end

endmodule







